/*
 *
 * 名称：罗盘
 * 功能：专让负责画罗盘
 * 作者：清河张
 * 时间：2025.05.24
 *
 */
#include "luopan.h"
#include <stdexcept>
#include <iostream>

static const qreal STARTENGLE = -90.0;
static const qreal STARTARC = -90.0 * M_PI / 180;

qreal ratioToRadians(qreal ratio) //一圈比例，转成弧度
{
    return - 2 * M_PI * ratio;
}

qreal divToRadians(qreal div) //分段，转成弧度
{
    return - 2 * M_PI / div;
}


void WYLQRINGITEM::setbase(qreal r1, qreal thikness)
{
    _r1 = r1;
    _r2 = r1 + thikness;
    _d1 = _r1 * 2;
    _d2 = _r2 * 2;
    _r = (_r1 + _r2) / 2;
}

void WYLQRINGITEM::putPath(qreal startRadians, qreal arcRadians, QPainterPath &path)
{
    path.clear();

    qreal startAngle = qRadiansToDegrees(startRadians);
    qreal arcAngle = qRadiansToDegrees(arcRadians);

    QPointF pa (
        _cx + _r1 * std::cos(startRadians),
        _cy - _r1 * std::sin(startRadians) );

    QPointF pb (
        _cx + _r2 * std::cos(arcRadians + startRadians),
        _cy - _r2 * std::sin(arcRadians + startRadians) );

    path.moveTo(pa);
    path.arcTo(_cx - _r1, _cy - _r1,
               _d1, _d1,
               startAngle, arcAngle );
    path.lineTo(pb);
    path.arcTo(_cx - _r2, _cy - _r2,
               _d2, _d2,
               startAngle + arcAngle, - arcAngle );
    path.lineTo(pa);
    path.closeSubpath();
}

void WYLQRINGITEM::putTextItem(qreal angleTextRadians, QGraphicsTextItem *textItem)
{
    qreal nx, ny;
    QTransform transform;
    QPointF textCenter;

    qreal angleText = qRadiansToDegrees(angleTextRadians);

    textItem->setDefaultTextColor(Qt::white);
    textItem->setFlag(QGraphicsItem::ItemIgnoresTransformations);
    textCenter = textItem->boundingRect().center();
    textItem->setTransformOriginPoint(textCenter);
    textItem->setRotation( STARTENGLE - angleText );

    nx = _cx - textCenter.x();
    ny = _cy - textCenter.y();
    transform.translate(nx, ny);
    textItem->setTransform(transform);

    if(_r1 > 0)
    {
        qreal ax = _r * qCos ( angleTextRadians );
        qreal ay = _r * qSin ( angleTextRadians );
        textItem->moveBy(ax,-ay);
    }
}

void WYLQRINGITEM::angleToPos(qreal radians, qreal &x, qreal &y)
{
    qreal ox, oy;
    ox = _r * std::cos( radians );
    oy = _r * std::sin( radians );
    x = _cx + ox;
    y = _cy - oy;
}

qreal WYLQRINGITEM::fontpixels(qreal radians, int ntext)
{
    qreal fontwidth = std::abs ( _r1 * radians) / ntext;
    qreal fontheight = ( _r2 - _r1 );
    return fontheight > fontwidth ? fontwidth : fontheight;
}


LUOPAN::LUOPAN(QGraphicsScene *ss):_ss(ss)
{
    ss->setBackgroundBrush(Qt::black);
}


void LUOPAN::huashen(const LUOPAN::SHENPAN& shenpan)
{
    int sz;
    qreal r1, thikness, cx, cy, r;

    QGraphicsTextItem *textItem;

    _ss->clear();
    sz = shenpan.size();
    r = _ss->sceneRect().width() / 2;
    thikness = r / sz;
    r1 = thikness * 0.6;
    cx = _ss->sceneRect().center().x();
    cy = _ss->sceneRect().center().y();

    WYLQRINGITEM item = {cx,cy,0,0,0,0,0};
    textItem = _ss->addText("中");

    item.putTextItem( STARTARC , textItem );

    for ( int i = 0; i < sz; ++i)
    {
        try {
            const SHENFU& shenattr = shenpan.at(i);
            huafu(shenattr, item, r1, thikness);
            r1 += thikness;
        } catch (const std::out_of_range& e) {
            std::cerr << "Error: " << e.what() << std::endl;
        } catch (const std::exception& e) {
            std::cerr << "An error occurred: " << e.what() << std::endl;
        } catch (...) {
            std::cerr << "An unknown error occurred." << std::endl;
        }
    }
}

void LUOPAN::huafu(const SHENFU& shenattr, WYLQRINGITEM& itemtmp, qreal r1, qreal thiknees)
{
    qreal arcRadians, startRadians, nx, ny, fz ;
    QPainterPath path;
    QGraphicsTextItem *textItem;
    QFont xsfont("楷体"), tipsfont("黑体");

    arcRadians = divToRadians(shenattr._strs.size());
    itemtmp.setbase( r1, thiknees );

    fz = itemtmp.fontpixels(arcRadians, shenattr._ntext);
    xsfont.setPixelSize( fz );

    startRadians = STARTARC + shenattr._startRadians;

    for ( size_t j = 0; j < shenattr._strs.size(); ++j )
    {
        itemtmp.putPath(startRadians, arcRadians, path);
        _ss->addPath(path,QPen(Qt::yellow),QBrush(shenattr._yy ? Qt::blue : Qt::gray));
        textItem = _ss->addText(shenattr._strs[j], xsfont);
        itemtmp.putTextItem(startRadians + arcRadians / 2, textItem);

        startRadians += arcRadians;
    }

    fz *= 0.6;
    for(size_t i = 0; i < shenattr._tishi.size(); ++i)
    {
        const SHENFU::TISHI & tishi = shenattr._tishi[i];

        itemtmp.angleToPos(STARTARC + shenattr._startRadians + tishi._offsetRadians, nx, ny );
        _ss->addEllipse( nx - 2, ny - 2, 4, 4, QPen(Qt::magenta),QBrush(Qt::red));

        tipsfont.setPixelSize( fz );
        textItem = _ss->addText(tishi._name,tipsfont);
        textItem->setDefaultTextColor(Qt::red);
        textItem->setFlag(QGraphicsItem::ItemIgnoresTransformations);
        textItem->setPos(nx - fz * 0.5,ny);
    }
}
